{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# The Time Axis: GRBs Over Time\n",
    "\n",
    "This notebook will demonstrate some of what you can do with WWT’s clock using a dataset of [gamma-ray burst](https://en.wikipedia.org/wiki/Gamma-ray_burst) events."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "---\n",
    "\n",
    "## Step 1: Setting up WWT\n",
    "\n",
    "First, we need to connect to the WWT app. If WWT isn't running yet, activate the JupyterLab command palette from the View menu, and select \"WorldWide Telescope\". Then all we need to do is run:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from pywwt.jupyter import connect_to_app\n",
    "wwt = await connect_to_app().becomes_ready()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now the `wwt` variable will let us talk to the WWT app.\n",
    "\n",
    "We'll also set up a utility function to help locate the data files stored alongside this notebook:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def datapath(*args):\n",
    "    from os.path import join\n",
    "    return join('data', *args)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "---\n",
    "\n",
    "## Step 2: Loading tabular data with a time-series axis\n",
    "\n",
    "Now that the viewer is set up, we need some data. First, some imports:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from astropy.coordinates import SkyCoord\n",
    "from astropy.table import Table\n",
    "from astropy.time import Time, TimeDelta\n",
    "from astropy import units as u\n",
    "from datetime import datetime"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now, we'll load up a table of GRB data. We'll print out the first few rows to get a sense of the data structure. In this case it's pretty simple."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "bursts = Table.read(datapath('grb_table_lite.ecsv'), format='ascii.ecsv')\n",
    "bursts[:5]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The WWT engine doesn't know enough to know that the Julian Date values above are actually dates (and not just some random floating-point measurements), so we convert them to the ISO8601 format:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "bursts['dates_ISOT'] = Time(bursts['dates_JD'], format='jd').isot\n",
    "bursts[:5]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "---\n",
    "\n",
    "## Step 3: Plotting Data in (2+1)D\n",
    "\n",
    "To start showing the data, we create a \"table layer\":"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "layer = wwt.layers.add_table_layer(\n",
    "    table = bursts, \n",
    "    frame = 'Sky', \n",
    "    lon_att = 'ra',  # treat the column named \"ra\" as a longitude coordinate\n",
    "    lat_att = 'dec',  # likewise for the column named \"dec\"\n",
    "    size_scale = 200,\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now let's tell the engine that we want to pay attention to the time axis of the table. **This will make all of the points disappear**, since the engine's clock is synchronized to your computer — it's plotting data for the current year, and our GRBs only go up to 2014."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "layer.time_series = True\n",
    "layer.time_att = 'dates_ISOT'"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We can check the engine's clock using the `get_current_time()` method:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "wwt.get_current_time()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Let's demonstrate that things are actually working by centering on the first GRB in both space *and* time — setting the WWT clock to just before it goes off."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "first_grb = bursts[0]\n",
    "start_pos = SkyCoord(first_grb['ra'], first_grb['dec'], unit=u.deg)\n",
    "start_time = Time(first_grb['dates_ISOT'], format='isot') - TimeDelta(5 * u.second)\n",
    "\n",
    "wwt.center_on_coordinates(start_pos)\n",
    "wwt.set_current_time(start_time)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "You should see a white dot appear in the screen center after five seconds!\n",
    "\n",
    "The WWT timeseries support has the concept of a \"decay time\". Points that appear on the screen slowly fade over the decay timescale — according to the WWT simulation clock, that is, not wallclock time. The default is 16 days. That's a bit short for visualizing GRBs, so let's make it longer:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "layer.time_decay = 1 * u.yr"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now, let's speed time up to see the GRBs pop off over time. If you find the right patch of the sky (namely, the ecliptic), you might also see the Sun and planets moving around at enhanced speed."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "wwt.play_time(rate=3e6)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Once you've had your fill, the following function call will reset the clock to run at real time:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "wwt.play_time()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "How much time passed inside WWT?"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "wwt.get_current_time() - start_time"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "---\n",
    "\n",
    "## Credits\n",
    "\n",
    "This notebook was prepared by:\n",
    "\n",
    "- O. Justin Otor\n",
    "- Peter K. G. Williams\n",
    "\n",
    "With thanks to Mark SubbaRao for creating the first version of this demonstration."
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
